package model;

import java.net.URL;
import java.net.URISyntaxException;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.LinkedList;
import java.util.LinkedHashSet;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.Comparator;
import java.lang.reflect.Member;
import util.*;
public class Copy_2_of_TestClusterBuilder {
	private final Map<String,Class<?>> classToTest ;
	private final Map<String, CUT> cluster;
	private final Map<String, String[]>  refFactory;
	private final List<StatementKind>  statements;
	private Set<Class<?>> packageClasses= new HashSet<Class<?>>();
//	private Set<Class<?>> toDo = new HashSet<Class<?>>();
	public Copy_2_of_TestClusterBuilder(Set<Class<?>> allClasses) {
	       // This block configure the logger with handler and formatter  

		cluster = new LinkedHashMap<String, CUT>();
		refFactory= new LinkedHashMap<String, String[]>();
		statements=new LinkedList<StatementKind>();
		classToTest= new LinkedHashMap<String,Class<?>>();
		
		filterUntestableClasses(allClasses);
		if(classToTest.size()==0){
			System.err.println("TestClusterBuilder.TestClusterBuilder: There are no Classes To Test!"+ allClasses.toString());
	//		System.exit(0);
			//return null;
		}
		else{
		    addPublicStaticMethodFromAbstracts(statements, allClasses);
			calculateCluster();
			createRefMap();

		}
	}
	public Map<String,Class<?>>  getClassToTest(){
		return classToTest;
	}
	public List<StatementKind>  getStatements(){
		return statements;
	}

	public  Map<String, String[]>   getRefFactory(){
		return refFactory;		
	}
	public  Map<String, CUT>   getCluster(){
		return cluster;		
	}
	public CUT getCluster(String cName) {
		return cluster.get(cName) ;
	}

	public CUT getCut() {
		return cluster.get(classToTest.keySet().toArray()[Randomness.nextRandomInt(classToTest.size())]);
	}
	public CUT getClassCluster() {
		return cluster.get(cluster.keySet().toArray()[Randomness.nextRandomInt(cluster.size())]);
	}
	private Set<Class<?>>  calculate_classes(Class<?> clazz)  {
	System.out.println ("calculate_classes: paramater  java.lang.Class" );
	Set<Class<?>> loop = new HashSet<Class<?>>();
	Set<Class<?>> toDo = new HashSet<Class<?>>();
	loop.addAll(getClassToTest().values());
			Package package1 = clazz.getPackage();
//				System.out.println("Package class:  " +  clazz.getName() );
		Set<Class<?>> exisitClass= new HashSet<Class<?>>(this.getClassesForPackage(package1)); 
//		System.out.println("exisitClass:  " +  exisitClass);
		for(Class<?> c:exisitClass){
			if(Filter.isAbstract(c) || !Filter.isVisible(c.getModifiers())) continue;
				loop.add(c);
		}
//		packageClasses.addAll(exisitClass);
        

	while(!loop.isEmpty()) {
		Class<?> clazz_ = loop.iterator().next();
		loop.remove(clazz_);
	      for (Field f : clazz_.getDeclaredFields()) {
	    	  if(f.getType().equals(java.lang.Class.class)){
	    		  toDo.add(clazz_);
	    		  break;
	    	  }
	    	  
	      }
	      if(toDo.contains(clazz_))continue;
	      for (Method m : getMethodsOrdered(clazz_)) {
	    	  final Class<?> returnType = m.getReturnType();
	    	  if(returnType.equals(java.lang.Class.class)){
	    		  if(!toDo.contains(clazz_)){
	    			  toDo.add(clazz_);
	    		  }
    			  break;

	    	  }
	    	  
	      }
	}
	return toDo;
	}
	private void calculateCluster()  {
		if(DebugConfig.TestClusterBuilder)
		   Log.log(Level.INFO, " TestClusterBuilder.calculateCluster");
		List<Class<?>> considerClasses=new LinkedList<Class<?>>();
		Set<Class<?>> toDo = new HashSet<Class<?>>();
		toDo.addAll(getClassToTest().values());
		while(!toDo.isEmpty()) {
			Class<?> clazz = toDo.iterator().next();
			toDo.remove(clazz);
			String className=clazz.getName();
			System.out.println("Consider Class:  " +  className + " to be added to cluster");
			if(clazz.equals(Comparable.class)) 
				toDo.add(Integer.class);
//			if(className.contains("$"))continue;
			if(Filter.isObjectType(clazz))continue;
			if(cluster.get(className) != null)continue;
			if(packageClasses.contains(clazz)) continue;

				
		     	Set<ConstructorDeclared> cList = new LinkedHashSet<ConstructorDeclared>();
	     		Set<MethodDeclared> methodToTest = new LinkedHashSet<MethodDeclared>();
	     		Set<PublicFieldDeclared> fieldDeclared= new LinkedHashSet<PublicFieldDeclared>();
	     		Set<ConstantDeclared> constantDeclared= new LinkedHashSet<ConstantDeclared>();

	     		if(Filter.isPrimitiveOrStringType(clazz)||clazz.isArray()){
	                MethodDeclared[] methods = methodToTest.toArray(new MethodDeclared[methodToTest.size()]);
		 			ConstructorDeclared[] constructors = cList.toArray(new ConstructorDeclared[cList.size()]);
		            PublicFieldDeclared[] fields = fieldDeclared.toArray(new PublicFieldDeclared[fieldDeclared.size()]);
		            ConstantDeclared[] constants = constantDeclared.toArray(new ConstantDeclared[constantDeclared.size()]);

		 	//		CUT.getConstructor(clazz,constructors,fields, methods,constants);
					CUT cut=CUT.getConstructor(clazz,constructors,fields, methods,constants);
					cluster.put(clazz.getName(),cut);
					continue;
	     		}
	     		if(!clazz.getName().startsWith("java")&&!clazz.getName().startsWith("sun")){
		         if(!packageClasses.contains(clazz)) {
		 			Package package1 = clazz.getPackage();
	//				System.out.println("Package class:  " +  clazz.getName() );
					Set<Class<?>> exisitClass= new HashSet<Class<?>>(this.getClassesForPackage(package1)); 
//					System.out.println("exisitClass:  " +  exisitClass);
					for(Class<?> c:exisitClass){
						if(Filter.isAbstract(c) || !Filter.isVisible(c.getModifiers())) continue;
						if(CanBeUsedAs.canBeUsedAs(c,clazz))
							toDo.add(c);
					}
					if(Filter.isAbstract(clazz)||!Filter.isVisible(clazz.getModifiers())){
							toDo.remove(clazz);
							  continue;
					}
					packageClasses.add(clazz);
//					packageClasses.addAll(exisitClass);
		            
		            }
	     		}
	     		Constructor<?>[] allConstructors = clazz.getDeclaredConstructors();
		     	considerClasses.add(clazz);
	             for (Constructor<?> co : allConstructors) {
	                if (Filter.canUse(co)) {
	    				if(DebugConfig.TestClusterBuilder)
	    						Log.log(  co.toString() + " to cluster");
	                	ConstructorDeclared con = ConstructorDeclared.getConstructor(co);
						// add the parameters and return type to the test cluster
						for(Class<?> param :co.getParameterTypes()){
//							if(param.isArray()) continue;
									toDo.add(param);
						}

	                	statements.add(con);	                	
	                	cList.add(con);
	                }
					for(Class<?> param : co.getParameterTypes()){
//						if(param.isArray()) continue;
						toDo.add(param);
					}

	              }
	             if(clazz.getName().startsWith("java")||clazz.getName().startsWith("sun")){
			            ConstantDeclared[] constants = constantDeclared.toArray(new ConstantDeclared[constantDeclared.size()]);
		                MethodDeclared[] methods = methodToTest.toArray(new MethodDeclared[methodToTest.size()]);
			 			ConstructorDeclared[] constructors = cList.toArray(new ConstructorDeclared[cList.size()]);
			            PublicFieldDeclared[] fields = fieldDeclared.toArray(new PublicFieldDeclared[fieldDeclared.size()]);
	 				Arrays.sort(constructors);
					CUT cut=CUT.getConstructor(clazz,constructors,fields, methods,constants);
	 				cluster.put(clazz.getName(),cut);
	 				continue;
	             }
//					if(classToTest.containsKey(clazz.getName())){// continue;

	             List <Method> alreadUsed=new LinkedList<Method>();
	             for (Method m : getMethodsOrdered(clazz)) {
	            		                if(alreadUsed.contains(m)) continue;
	            		                alreadUsed.add(m);
	            		               if (Filter.canUse(m)) {
		           		                System.out.printf ("\tConsidering method %s%n", m);
	            		            	   MethodDeclared mc =  MethodDeclared.getMethod(m);
	            		            	   statements.add(mc);
	            		            	   methodToTest.add(mc);
	            							// add the parameters and return type to the test cluster
	            							for(Class<?> param : m.getParameterTypes()){
//	            								if(param.isArray()) continue;
//	            								System.out.printf ("\tConsidering method paramater %s%n", param);
	            										toDo.add(param);
	            							     		if(param.getName().equals("java.lang.Class")) 
	            							     			toDo.addAll(calculate_classes(clazz));

	            							}
	            							final Class<?> returnType = m.getReturnType();
	            							if(returnType==Void.TYPE ) continue;// arrays are supported via additional methods
	            							toDo.add(m.getReturnType());
//            								System.out.printf ("\tConsidering return method  %s%n", m.getReturnType());
//	            							if(DebugConfig.TestClusterBuilder)
//	            								Log.log(statements.size()+ " " +  m.toString() + " to test");

	            		               }
	            		             }
	//				}
//	             constantDeclared.addAll(calculateConstants(clazz));
//		          fieldDeclared.addAll(calculatePublicFields(clazz));
		     
		            ConstantDeclared[] constants = constantDeclared.toArray(new ConstantDeclared[constantDeclared.size()]);
	                MethodDeclared[] methods = methodToTest.toArray(new MethodDeclared[methodToTest.size()]);
		 			ConstructorDeclared[] constructors = cList.toArray(new ConstructorDeclared[cList.size()]);
		            PublicFieldDeclared[] fields = fieldDeclared.toArray(new PublicFieldDeclared[fieldDeclared.size()]);
					Arrays.sort(constructors);
					CUT cut=CUT.getConstructor(clazz,constructors,fields, methods,constants);
			cluster.put(clazz.getName(),cut);
				toDo.addAll(calculateSubClasses(clazz));

		}//while
	}
	private Set<Class<?>> calculateSubClasses(Class<?> cls){
		Set<Class<?>> parents= new LinkedHashSet<Class<?>>();
		Class<?> c = cls.getSuperclass();
		while(c != null) {
			parents.add(c);
			for(Class<?> i : c.getInterfaces())
				parents.add(i);

			c = c.getSuperclass();
		}
		return parents;
	}
	private  ArrayList<Class<?>> getClassesForPackage(Package pkg) {
	    String pkgname = pkg.getName();
	    ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
	    // Get a File object for the package
	    File directory = null;
	    String fullPath;
	    String relPath = pkgname.replace('.', '/');
//	    System.out.println("ClassDiscovery: Package: " + pkgname + " becomes Path:" + relPath);
	    URL resource = ClassLoader.getSystemClassLoader().getResource(relPath);
//	    System.out.println("ClassDiscovery: Resource = " + resource);
	    if (resource == null) {
	        throw new RuntimeException("No resource for " + relPath);
	    }
	    fullPath = resource.getFile();
//	    System.out.println("ClassDiscovery: FullPath = " + resource);

	    try {
	        directory = new File(resource.toURI());
	    } catch (URISyntaxException e) {
	        throw new RuntimeException(pkgname + " (" + resource + ") does not appear to be a valid URL / URI.  Strange, since we got it from the system...", e);
	    } catch (IllegalArgumentException e) {
	        directory = null;
	    }
//	    System.out.println("ClassDiscovery: Directory = " + directory);

	    if (directory != null && directory.exists()) {
	        // Get the list of the files contained in the package
	        String[] files = directory.list();
	        for (int i = 0; i < files.length; i++) {
	            // we are only interested in .class files
	            if (files[i].endsWith(".class")) {
	                // removes the .class extension
	                String className = pkgname + '.' + files[i].substring(0, files[i].length() - 6);
//	                System.out.println("ClassDiscovery: className = " + className);
	                try {
	                    classes.add(Class.forName(className));
	                } 
	                catch (ClassNotFoundException e) {
	                    throw new RuntimeException("ClassNotFoundException loading " + className);
	                }
	            }
	        }
	    }
	    return classes;
	}	
	  public static Method[] getMethodsOrdered(Class<?> c) {
		  List<Method> ms = new ArrayList<Method>();
	//       ms.addAll(Arrays.asList(c.getMethods()));
	        System.out.printf ("methods = %s%n", Arrays.toString(c.getDeclaredMethods()));
	       ms.addAll(Arrays.asList(c.getDeclaredMethods()));

		  Method[] ret = ms.toArray(new Method[0]);
		  Arrays.sort(ret, SORT_MEMBERS_BY_NAME);
		  return ret;
	  }
	  public static final Comparator<Member> SORT_MEMBERS_BY_NAME = new Comparator<Member>() {
		    public int compare(Member o1, Member o2) {
		      return o1.toString().compareTo(o2.toString());
		    }
		  };
	   private void addPublicStaticMethodFromAbstracts(List<StatementKind> statements, Set<Class<?>> allClasses) {
			if(DebugConfig.TestClusterBuilder)
					Log.log(Level.INFO, " TestClusterBuilder.addPublicStaticMethodFromAbstracts");
	     	Set<ConstructorDeclared> cList = new LinkedHashSet<ConstructorDeclared>();
     		Set<ConstantDeclared> constantDeclared= new LinkedHashSet<ConstantDeclared>();
     		Set<PublicFieldDeclared> fieldDeclared= new LinkedHashSet<PublicFieldDeclared>();

	     	Set<MethodDeclared> methodToTest = new LinkedHashSet<MethodDeclared>();
		      for(Class<?> clazz : allClasses) {
		        if(Filter.isAbstract(clazz) && Filter.isVisible(clazz)) {
					if(DebugConfig.TestClusterBuilder)
						Log.log("\t\t"+statements.size()+"\t"+clazz.getName());

		          Method[] methods = clazz.getDeclaredMethods();
		          for(Method method : methods) {
		            int modifier = method.getModifiers();
		            Class<?> returnType = method.getReturnType();
		            Class<?>[] paramTypes = method.getParameterTypes();
		            if(Modifier.isStatic(modifier) && Modifier.isPublic(modifier) && Filter.isVisible(returnType)
		                && Filter.areAllVisible(paramTypes)) {
		            	MethodDeclared mc =  MethodDeclared.getMethod(method);
		              //add here
		              statements.add(mc);
		              methodToTest.add(mc);
					  if(DebugConfig.TestClusterBuilder)
							Log.log("\t\t"+ statements.size()+ "\t\t"+statements.toString());

		            }
		          }
		        }
		        if(methodToTest.size()!=0){
		            ConstantDeclared[] constants = constantDeclared.toArray(new ConstantDeclared[constantDeclared.size()]);
	                MethodDeclared[] methods = methodToTest.toArray(new MethodDeclared[methodToTest.size()]);
		 			ConstructorDeclared[] constructors = cList.toArray(new ConstructorDeclared[cList.size()]);
		            PublicFieldDeclared[] fields = fieldDeclared.toArray(new PublicFieldDeclared[fieldDeclared.size()]);

						Arrays.sort(methods);
						CUT cut=CUT.getConstructor(clazz,constructors,fields, methods,constants);
				       // if(cluster.containsKey(clazz.getName())
				         cluster.put(clazz.getName(),cut);		
				        		
		        }
		        	
		      }
		    }

	    private Set<ConstantDeclared>  calculateConstants(Class<?> javaClass){
			Set<ConstantDeclared> constantDeclared = new LinkedHashSet<ConstantDeclared>();   
			 if(javaClass.getName().startsWith("java")||javaClass.getName().startsWith("sun"))  return constantDeclared;

//					System.out.println(" \tConsider define constants:  "+javaClass.toString() );
					      for (Field f : javaClass.getDeclaredFields()) {
//					    	  System.out.println(" \t TestClusterBuilder.calculateConstants:  "+javaClass.toString() );
					          // Check that @TestValue field is static.
					          if (!Modifier.isStatic(f.getModifiers())) continue;
//					          if(Modifier.isFinal(f.getModifiers())) continue;
					          // Check that @TestValue field is public.
					          if (!Modifier.isPublic(f.getModifiers())) continue;
					          
					          if (!Filter.canUse(f.getType())) continue;
					          // Get the value(s) stored in the field.
					         
					          ConstantDeclared field =  ConstantDeclared.getField(f);
					          statements.add(field);
					          constantDeclared.add(field);
					      }
				return constantDeclared;	      
	    }
	    private Set<PublicFieldDeclared>  calculatePublicFields(Class<?> javaClass){
			Set<PublicFieldDeclared> publicFieldDeclared = new LinkedHashSet<PublicFieldDeclared>(); 
			 if(javaClass.getName().startsWith("java")||javaClass.getName().startsWith("sun"))  return publicFieldDeclared;
//					System.out.println(" \tConsider define constants:  "+javaClass.toString() );
					      for (Field f : javaClass.getDeclaredFields()) {
//					    	  System.out.println(" \t TestClusterBuilder.calculateConstants:  "+f.toString() );
					          // Check that @TestValue field is static.
//					          if (!Modifier.isStatic(f.getModifiers())) continue;
					          
					          // Check that @TestValue field is public.
					          if (Modifier.isPrivate(f.getModifiers())||Modifier.isProtected(f.getModifiers())) continue;
					          if (!Filter.isPrimitiveOrStringType(f.getType())) continue;
					          
					         
					          PublicFieldDeclared field =  PublicFieldDeclared.getField(f);
					          statements.add(field);
					          publicFieldDeclared.add(field);
					      }
				return publicFieldDeclared;	      
	    }
    private  void filterUntestableClasses(Set<Class<?>> classes) {
		if(DebugConfig.TestClusterBuilder)
			Log.log(Level.INFO,"TestClusterBuilder.filterUntestableClasses" );
        
    	Map<String,Class<?>> retClasses = new LinkedHashMap<String, Class<?>>();
      //filter unvisible (non-public) and abstract classes
      for(Class<?> clazz : classes) {
          if(Filter.isAbstract(clazz) || !Filter.isVisible(clazz.getModifiers())) {
              continue;
            }
            classToTest.put(clazz.getName(),clazz);
//			if(DebugConfig.TestClusterBuilder)
//				Log.log(classToTest.size()+ " "+ clazz.getName()+ " classToTest");
      }      
    }
   
    
	 /**
     * Read from the provided class file 
     * */
    public static List<Class<?>>  readClassFromFile() {

    	List<Class<?>>   classToTest = new LinkedList<Class<?>>();

		if (GAConfig.classFilePath != null) {
//			System.out.println("Read tested class from file: "+ GAConfig.classFilePath);
			try {
				BufferedReader br = new BufferedReader(new FileReader(new File(
						GAConfig.classFilePath)));
				String line = br.readLine();
				while (line != null) {
					String className = line.trim();
					if (!className.equals("")&&!className.startsWith("//")) {
			               Class<?> clazz = Class.forName(className);
			               classToTest.add(clazz);
					}
					line = br.readLine();
				}
			}    catch (FileNotFoundException e) {
		          e.printStackTrace();
		          System.exit(0);
	        } catch (IOException e) {
	          e.printStackTrace();
	        } catch (ClassNotFoundException e) {
	          e.printStackTrace();
	          System.exit(0);
	        }

		}

		return classToTest;
}
    
	private void createRefMap() {
		if(DebugConfig.TestClusterBuilder)
		   Log.log(Level.INFO, " TestClusterBuilder.createRefMap");

			for( Entry<String, CUT> c : getCluster().entrySet()) {

				String[] refs = new String[GAConfig.NumVarCut];
				for(int i = 0; i < refs.length; i++)
					if(getCluster().get(c.getKey()).getClazz().isArray()){
						Class cls=getCluster().get(c.getKey()).getClazz();
						String ref=cls.getComponentType().toString().substring(cls.getComponentType().toString().lastIndexOf(".") + 1); 
						refs[i]= ref+"Array_" + i;
					}	
					else{
						refs[i] = c.getKey().substring(c.getKey().lastIndexOf(".") + 1)+ "_" + i;
					}

				refFactory.put(c.getKey(), refs);
				if(DebugConfig.TestClusterBuilder)
					Log.log(" \t\t " +refFactory.size() + " " + c.getKey());
			}
		}
	public static List<Copy_2_of_TestClusterBuilder> buildTestClusterList(Set<Class<?>> allClasses){
	      List<Copy_2_of_TestClusterBuilder> TestClusterList=new LinkedList<Copy_2_of_TestClusterBuilder>();
	      for(Class<?> cls: allClasses){
	    	  Set<Class<?>> classToAnalysis = new LinkedHashSet<Class<?>>();
	    	  classToAnalysis.add(cls);
		      Copy_2_of_TestClusterBuilder TestCluster = new Copy_2_of_TestClusterBuilder(classToAnalysis);
		      if(TestCluster.classToTest.size()!=0)
		    	  TestClusterList.add(TestCluster);

	      }
	      
	      return TestClusterList;
	}
	public  static void main(String args[]) throws ClassNotFoundException {
		if(DebugConfig.TestClusterBuilder){
			String logFilePath = "c:/MAMDA/MAMDA2014/temp/TestClusterBuilder.txt";
			Log.logConfig(logFilePath);
			new File(logFilePath).getAbsolutePath();
		}
	        // the following statement is used to log any messages  

		Randomness.reset(10);
		 Set<Class<?>> allClasses = new LinkedHashSet<Class<?>>();
	      //get class from file
	      allClasses.addAll(Copy_2_of_TestClusterBuilder.readClassFromFile());

	      System.out.println("There are " + allClasses.size() + " classes as input");
	      
	      System.out.println(allClasses);
	      List<Copy_2_of_TestClusterBuilder> TestClusterList= buildTestClusterList(allClasses);
	      for(Copy_2_of_TestClusterBuilder tCluster:TestClusterList){
		      Map<String,Class<?>> classesToTest = tCluster.classToTest;
		      System.out.println("There are " + classesToTest.size() + " classes to test after filtering");
		      System.out.println(" --------- classes to test ---------------");
		      System.out.println("\t" + classesToTest.keySet().toString());
		      System.out.println(" -----------------------------------------");
	
			// calculate the test cluster and the set of types involved in the
	//			TestClusterBuilder TestCluster = new TestClusterBuilder(classesToTest);
		      List<StatementKind>  statements=tCluster.statements;
		      List<String> ConstructorAsString = new ArrayList<String>(); // For testing purposes.
		      for (StatementKind st : statements)
		    	  if(st instanceof ConstructorDeclared&&st.toParseableString(classesToTest)!=null)
		    		  ConstructorAsString.add(st.toParseableString(classesToTest));
				System.out.println("  --------------------------------  ");
		    	System.out.println(ConstructorAsString.size() +"  Constructor   ");	
				System.out.println("  --------------------------------  ");
			      List<String> MethodToTestAsString = new ArrayList<String>(); // For testing purposes.
			      for (StatementKind st : statements)
		    	  if(st instanceof MethodDeclared&&st.toParseableString(classesToTest)!=null)
			    		  MethodToTestAsString.add(st.toParseableString(classesToTest));
					System.out.println("  --------------------------------  ");
			    	System.out.println(MethodToTestAsString.size() +"  method to test   ");	
					System.out.println("  --------------------------------  ");
					System.out.println(MethodToTestAsString.toString());
					if(DebugConfig.TestClusterBuilder){
						Log.log("  --------------------------------  ");
						Log.log(MethodToTestAsString.size() +"  method to test   ");	
						Log.log("  --------------------------------  ");
						Log.log(MethodToTestAsString.toString());
					}
	
		      if(statements.size() == 0) {
		          System.out.println("There is nothing to test!");
		          System.exit(0);
		        } else {
		          System.out.println("Num of all constructors/public to call : " + statements.size());
		        }
		      if(tCluster.getCluster().size()!=0){
					System.out.println("  ----------------- Cluster ---------------  ");
		          System.out.println("Size Cluster: " + tCluster.getCluster().size());
	
		      }
				for( Entry<String,  String[]> c : tCluster.getRefFactory().entrySet() ) {			
					if (false) continue;
					String[]mList = c.getValue();
					System.out.print("\t"+c.getKey() +" = " );
					 for(int i=0; i<mList.length;i++)
						 System.out.print(mList[i]+" , ");
					 System.out.println();
				}
	
	
		}
	}

}
